<?php


namespace App\Repositories;


use App\Exceptions\BusinessException;
use App\Foundation\Repository\Repository;
use App\Handlers\ImageUploadHandler;
use App\Models\Category;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;

class CategoriesRepository extends Repository
{

    public function model()
    {
        return Category::class;
    }


    /**
     * 查询所有的栏目-后台使用
     */
    public function all()
    {
        return $this->m()->get();
    }

    /**
     * 查询所有分类组成tree
     * @return array
     */
    public function getAll()
    {
        $data = $this->m()->where('flags',1)
            ->where('isindexnav',1)
            ->orderBy('corders','asc')
            ->get()->keyBy('id')->toArray();
        return $data ? $this->formatNestCategories($data) : [];
    }

    /**
     * 前台标签调用生成导航条
     * @return array
     */
    public function getNav()
    {
        $data = $this->getAll();
        $filtered = Arr::where($data, function ($value, $key) {
            return $value['isindexnav'] == 1;
        });
        return array_values($filtered); //对数组的key 重新按0 开始排序
    }

    /**
     * @param bool $is_tree
     * @return array
     */
    public function allFormatCategories($is_tree = false)
    {
        if($is_tree) {
            $cates = $this->m()->where('is_tree',1)->get()->keyBy('id')->toArray();
        }else {
            $cates = $this->all()->keyBy('id')->toArray();
        }
        return $cates ? $this->formatCates($cates) : [];
    }


    /**
     * 根据栏目层级调用指定的栏目
     * @param $id 如果是0 表示pid 是 0 的，调用全部分类
     * @param $level
     * @return array|\Illuminate\Support\Collection
     */
    public function getCateByidForLevel($id,$level) {
        $ids = $this->getCateid($id);
        $ids = is_array($ids) ? $ids : [$ids];
        $categories = $this->m()->whereIn('id',$ids)->get()->keyBy('id')->toArray();;

        $cas = $this->formatCates($categories);
        $collect = collect($cas);
        $ids = $collect->where('level',$level)->pluck('id')->toArray();
        return $ids;
    }

    /**
     * 根据栏目层级调用指定的栏目
     * @param $id 如果是0 表示pid 是 0 的，调用全部分类
     * @param $level
     * @return array|\Illuminate\Support\Collection
     */
    public function getCateByCidForLevel($id,$level) {
        $ids = $this->getCateid($id);
        $ids = is_array($ids) ? $ids : [$ids];
        $categories = $this->m()->whereIn('id',$ids)->get()->keyBy('id')->toArray();;
        $cas = $this->formatCates($categories);
        $collect = collect($cas);
        $ids = $collect->where('level',$level)->pluck('id')->toArray();
        return $ids;
    }

    /**
     * @param $cates
     * @param int $pid
     * @param int $level
     * @param string $html
     * @return array
     */
    public function formatCates($cates, $pid = 0, $level = 0,$html = '&nbsp&nbsp')
    {
        static $result;

        foreach ($cates as $cate) {
            if ($cate['pid'] === $pid) {
                $result[] = array_merge($cate, [
                    'level' => $level+1,
                    'html' => str_repeat($html.'┝'.'&nbsp', $level),
                    'parentName' => $cates[$pid]['cname'] ?? '顶级栏目',
                ]);
                $this->formatCates($cates, $cate['id'], $level + 1);
            }
        }
        return $result;
    }

    public function findByid($id)
    {
        $model = $this->m()->with('news','child','cate')->find($id);
        if (!$model) {
            throw new BusinessException('栏目不存在或已被删除');
        }
        return $model;
    }

    public function findBypid($id)
    {
        $model = $this->m()->where(['pid' => $id])->get()->toArray();
        if ($model) {
            throw new BusinessException('栏目下有子分类不能删除，清先删除子分类');
        }
    }

    public function delete(Category $model)
    {
        $news = $model->news->pluck('id')->toArray();
        if (!$news) {
            return false;
        }
        return $news;
    }


    /**
     * 根据id查找自身和它的所有父级
     * @param $cate
     * @param $id
     * @return array
     */
    function breadCrumbs($cate,$id){
        $arr=array();
        foreach($cate as $v){
            if($v['id']==$id){
                $arr[]=$v;// $arr[$v['id']]=$v['name'];
                $arr=array_merge($this->breadCrumbs($cate,$v['pid']),$arr);
            }
        }return $arr;

    }

    /**
     * 根据id查找子类
     * @param $cate 所有分类的数组
     * @param $id
     * @return array
     */
    function get_child($cate,$id){
        $arr=array();
        foreach($cate as $v){
            if($v['pid']==$id){
                $arr[]=$v;// $arr[$v['id']]=$v['name'];
                $arr=array_merge($this->get_child($cate,$v['id']),$arr);
            }
        }return $arr;

    }

    /**
     * 组合一维数组
     * @param $array
     * @param $field
     * @return array
     */
    function only_array($array, $field) {
        $arr = array();
        foreach ($array as $v) {
            $arr[] = $v[$field];
        }
        return $arr;
    }

    /**
     * 获取分类下的所有id包括自身
     * @param $id
     * @return array
     */
    public function getAllCateid($id)
    {
        $cates = $this->m()->get(['id','pid','cname']);
        $obj = $this->get_child($cates,$id);
        //如果能查到分类就把传递过来的id重新组合进数组
        if ($obj) {
            $ids = $this->only_array($obj,'id');
            $ids[] = intval($id);
            return $ids;
        } else {
            // 差不到直接返回id
            return $id;
        }
    }

    /**
     * 获取分类下的所有id包括自身
     * @param $id
     * @return array
     */
    public function getCateid($id)
    {
        $cates = $this->m()->where('flags',1)->get(['id','pid','cname']);
        $obj = $this->get_child($cates,$id);
        //如果能查到分类就把传递过来的id重新组合进数组
        if ($obj) {
            $ids = $this->only_array($obj,'id');
            $ids[] = intval($id);
            return $ids;
        }else {
            // 差不到直接返回id
            return $id;
        }
    }

    /**
     * 格式化栏目列表为树状结构
     * @param $permissions
     * @param int $pid
     * @return array
     */
    public function formatNestCategories($categories, $pid = 0)
    {
        // 不能用 static
        $result = array();
        foreach ($categories as $v) {
            if ($v['pid'] == $pid) {
                foreach ($categories as $subVal) {
                    if ($subVal['pid'] == $v['pid']) {
                        $v['children'] = $this->formatNestCategories($categories, $v['id']);
                        break;
                    }
                }
                $result[] = $v;
            }
        }
        return $result;
    }

    /**
     * 生成Ztree 数据结构
     * @param $categories
     * @param string $target
     * @return array
     */
    public function createTree($categories,$target='main')
    {
        // { id:1, pid:0, name:"一级分类", open:true},
        $tree = [];
        foreach ($categories as $key => $category) {
            $tree[$key]['id'] = $category['id'];
            $tree[$key]['pid'] = $category['pid'];
            $tree[$key]['cname'] = $category['cname'];
            if (!empty($category['children'])) {
                foreach ($category['children'] as $k => $child) {
                    $tree[$key]['children'][$k]['id'] = $child['id'];
                    $tree[$key]['children'][$k]['pid'] = $child['pid'];
                    $tree[$key]['children'][$k]['cname'] = $child['cname'];
                    $tree[$key]['children'][$k]['url'] = route('admin.contents.show',$child['id']);
                    $tree[$key]['children'][$k]['target'] = $target;
                    $tree[$key]['children'][$k]['open'] = true;
                    $tree[$key]['children'] = self::createTree($category['children']);
                }
            } else {
                $tree[$key]['url'] = route('admin.contents.show',$category['id']);
                $tree[$key]['target'] = $target;

            }
        }
        return $tree;
    }


    /**
     * 生成xm-select 数据结构
     * @param $categories
     * @param string $target
     * @return array
     */
    public function createUserCateTree($categories)
    {
        // { id:1, pid:0, name:"一级分类", open:true},
        $tree = [];
        foreach ($categories as $key => $category) {
            $tree[$key]['value'] = $category['id'];
            $tree[$key]['cname'] = $category['cname'];
            if (!empty($category['children'])) {
                foreach ($category['children'] as $k => $child) {
                    $tree[$key]['children'][$k]['value'] = $child['id'];
                    $tree[$key]['children'][$k]['cname'] = $child['cname'];
                    $tree[$key]['children'] = self::createUserCateTree($category['children']);
                }
            }
        }
        return $tree;
    }

    /**
     * 生成xm-select 数据结构
     * @param $categories
     * @param string $target
     * @return array
     */
    public function createXmSelect($categories)
    {
        // { id:1, pid:0, name:"一级分类", open:true},
        $tree = [];
        foreach ($categories as $key => $category) {
            if (($category['pid'] == 0 && !empty($category['children'])) || $category['children']) {
                $tree[$key]['disabled'] = true;
                $tree[$key]['value'] = $category['id'];
                $tree[$key]['cname'] = $category['cname'];
            } else {
                $tree[$key]['value'] = $category['id'];
                $tree[$key]['cname'] = $category['cname'];
            }


            if (!empty($category['children'])) {

                $tree[$key]['children'] = self::createXmSelect($category['children']);
            }

        }
        return $tree;
    }

    /**
     * 获取ztree列表 缓存加载
     * @return mixed
     */
    public  function getTree($categories) {
        // 尝试从缓存中取出 cache_key 对应的数据。如果能取到，便直接返回数据。
        // 否则运行匿名函数中的代码来取出活跃用户数据，返回的同时做了缓存。
        return Cache::remember($this->cache_key, $this->cache_expire_in_seconds, function () use($categories){
            return $this->createTree($categories);
        });
    }

    /**
     * 缓存栏目列表
     * @param $categories
     */
    private function cacheCategories($categories) {
        // 将数据放入缓存中
        Cache::put($this->cache_key, $categories, $this->cache_expire_in_seconds);
    }

    public function getChild($id)
    {
        $info = $this->m()->where('pid',$id)->get();
        if ($info->isEmpty()) {
            return false;
        }else {
            return true;
        }
    }

    /**
     * 栏目更新
     * @param $request
     * @param $id
     * @return \Illuminate\Http\JsonResponse
     *
     */
    public function update($request, $id)
    {
        try{
            $cate = repository()->categories->findByid($id);
            $data = [
                'cname' => trim($request->cname),
                'aliasname' => $request->aliasname ?? '',
                'pid' => $request->pid,
                'url' => $request->url ?? '',
                'template' => $request->template ?? '',
                'categories_tpl' => $request->categories_tpl ?? '',
                'list_tpl' => $request->list_tpl ?? '',
                'detail_tpl' => $request->detail_tpl ?? '',
                'special_tpl' => $request->special_tpl ?? '',
                'corders' => $request->corders,
                'isindexnav' =>$request->isindexnav,
                'ismenu' => $request->ismenu,
                'is_tree' => $request->is_tree,
                'flags' => $request->flags,
                'show_body' => $request->show_body,
                'is_single' => $request->is_single,
            ];
            if ($request->image) {
                $data['img_url'] = $this->imgUpload($request,new ImageUploadHandler(),'image');
            }
            $this->relationWithCate($cate, $data);

        }catch (\Exception $e) {
            return user_business_handler()->fail($e->getMessage());
        }
        return user_business_handler()->success('', '栏目更新成功');

    }

    //创建栏目

    public function store($request)
    {
        $data = [
            'cname' => trim($request->cname),
            'aliasname' => $request->aliasname ?? '',
            'pid' => $request->pid,
            'url' => $request->url ?? '',
            'template' => $request->template ?? '',
            'categories_tpl' => $request->categories_tpl ?? '',
            'list_tpl' => $request->list_tpl ?? '',
            'detail_tpl' => $request->detail_tpl ?? '',
            'special_tpl' => $request->special_tpl ?? '',
            'corders' => $request->corders,
            'isindexnav' =>$request->isindexnav,
            'ismenu' => $request->ismenu,
            'is_tree' => $request->is_tree,
            'show_body' => $request->show_body,
            'is_single' => $request->is_single,
            'img_url' => $request->image ? $this->imgUpload($request,new ImageUploadHandler(),'image') : '',
        ];
        if ($request->pid) {
            $count =  repository()->news->getCountBypid($request->pid);
            if ($count >0) {
                return user_business_handler()->error('当前分类下已关联文章无法创建子分类，请将文章调整到其他分类在尝试创建');
            }
        }

        repository()->categories->m()->create($data);
        return user_business_handler()->success('', '栏目创建成功');
    }

    // 级联更新栏目

    public function relationWithCate(Category $Category,$data){
        // 如果栏目是顶级栏目则更新下级状态


            if($Category->child->isEmpty()) {
                $Category->update($data);
            }else {
                DB::beginTransaction();

                if ($Category->update($data)) {
                    $ids = $ids = $this->getAllCateid($Category->id);
                    $route = \Request::route()->getName();

                    if ($route == 'admin.categories.status') {

                        $res = $this->m()->whereIn('id', $ids)->update(['flags' => $data['flags']]);

                    } elseif ($route == 'admin.categories.update') {

                        $res = $this->m()->whereIn('id', $ids)->update(['flags' => $data['flags'],'is_tree'=>$data['is_tree']]);
                    }


                    if ($res) {

                        DB::commit();

                    } else {
                        DB::rollBack();
                        throw new BusinessException('更新失败');
                    }
                }
            }

    }

    /**
     * 删除图片
     * @param Request $request
     * @param $id
     * @return \Illuminate\Http\JsonResponse
     */
    public function delImg(Request $request,$id)
    {
        try{
            $path = $request->images;
            $flag = unlink(public_path($path));
            if ($flag) {
                $cate = $this->findByid($id);
                $cate->img_url = null;
                $cate->save();
                return user_business_handler()->success('', '删除成功');
            }
        }catch (BusinessException $e) {
            return user_business_handler()->fail($e->getMessage());
        }
    }


}
